#include "Tools.h"


void DataTransfer::addNeighborsWeighting(pMesh mesh){

const double c1 = ( isHalfWeighting() )?0.5:0.6;
const double c2 = ( isHalfWeighting() )?0.1666666666:0.1;
  cout<<"c1: "<<c1<<endl;
  cout<<"c2: "<<c2<<endl;

	//Loop over vertices
	VIter vit = M_vertexIter(mesh);
	while ( pEntity vertex = VIter_next(vit) ){

		//variables
		double xyz[3], Interpolated_value; 
		pEdge Remember_elementEdges[3];

		V_coord(vertex,xyz);
		int id_vertex = EN_id(vertex);
		Interpolated_value = c1*getInterpolatedValues(id_vertex);
		//cout<<" InterpVal: "<<Interpolated_value<<endl;

		// search entity in which the point above are
		pEntity element = (pEntity)Octree_Search(xyz,theOctree);

		//store the element edges
		for(int i=0;i<3;i++){
			pEntity edge = element->get(1,i);
			Remember_elementEdges[i] = edge;
		}

		//select one of the element vertices to find its neighbours
		int number = 0; 
		double Neigh_Contribution = 0;
		for(int i=0;i<3;i++){

			pEntity vertice = element->get(0,i);		
			int NumFaces = V_numFaces(vertice);

			for (int j=0;j<NumFaces;j++){
				pEntity Face = vertice->get(2,j);

				//once one element is chosen, it is asked if it is a neighbour or not
				if(Face!=element){
					int cont = 0; 
					for(int k=0;k<3;k++){

						//distinguish if neighbours have an edge or a vertice in commom with the element 
						pEntity N_Edge = Face->get(1,k);
						if(N_Edge == Remember_elementEdges[1] || N_Edge == Remember_elementEdges[2] || N_Edge == Remember_elementEdges[3]){
							pEntity Element_vertice1 = N_Edge->get(0,0);
							pEntity Element_vertice2 = N_Edge->get(0,1);
							for(int l=0;l<3;l++){

								//choose the vertice that does not belong to the element
								pEntity Neighbour_vertice = Face->get(0,l);
								if(Neighbour_vertice != Element_vertice1 && Neighbour_vertice != Element_vertice2){
									int id = EN_id(Neighbour_vertice);
									double value = Interpolated_value + c2*getNodeValue(id);
									setInterpolatedValues(id_vertex,value);
								}
							}
						}
						else{
							cont++;
						}

//COLOCAR COMENTARIOS SOBRE O QUE CADA IF, FOR, WHILE FAZEM!!!!
						if(getRestrictionOperator() == FULL_WEIGHTING && cont == 3){
							for(int l=0;l<3;l++){

								//choose the vertices that do not belong to the element
								pEntity Neighbour_vertice = Face->get(0,l);
								if (Neighbour_vertice != vertice){

									number += 1;
									int id = EN_id(Neighbour_vertice);
									Neigh_Contribution += c2*getNodeValue(id);
								} 
							}
						}
					}
				}
			}
			//avoid divide a number by zero
			 if (number == 0) number = 1;
			 
			//add neighbourhood contribution (for the elements that share the same vertice)
			double value = getInterpolatedValues(id_vertex) + Neigh_Contribution/number;
			setInterpolatedValues(id_vertex,value);
		}
	}
}

bool DataTransfer::isHalfWeighting() {
  
  if (getRestrictionOperator() == HALF_WEIGHTING) return true;
  else return false;
}
  
